<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>时间轮(Time Wheel)技术解析</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background-color: #f8f9fa;
            color: #333;
            line-height: 1.6;
        }
        .hero {
            background: linear-gradient(135deg, #6e8efb 0%, #a777e3 100%);
            color: white;
            position: relative;
            overflow: hidden;
        }
        .hero-content {
            position: relative;
            z-index: 2;
        }
        .hero::before {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: url('');
            opacity: 0.6;
        }
        .card {
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
            border-radius: 12px;
            overflow: hidden;
            background: white;
        }
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
        }
        .code-block {
            background: #2d2d2d;
            color: #f8f8f2;
            border-radius: 8px;
            position: relative;
        }
        .code-header {
            background: rgba(0, 0, 0, 0.2);
            padding: 8px 16px;
            border-top-left-radius: 8px;
            border-top-right-radius: 8px;
            display: flex;
            align-items: center;
        }
        .code-dots {
            display: flex;
            margin-right: 12px;
        }
        .dot {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            margin-right: 6px;
        }
        .dot-red {
            background: #ff5f56;
        }
        .dot-yellow {
            background: #ffbd2e;
        }
        .dot-green {
            background: #27c93f;
        }
        .section-title {
            position: relative;
            padding-bottom: 10px;
            margin-bottom: 20px;
        }
        .section-title::after {
            content: "";
            position: absolute;
            bottom: 0;
            left: 0;
            width: 60px;
            height: 3px;
            background: linear-gradient(90deg, #6e8efb, #a777e3);
            border-radius: 3px;
        }
        .highlight-text {
            background: linear-gradient(90deg, #f6d365, #fda085);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            font-weight: 600;
        }
        .feature-icon {
            font-size: 24px;
            color: #6e8efb;
            margin-right: 12px;
        }
        .mermaid-container {
            background: white;
            border-radius: 12px;
            padding: 24px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
        }
        a {
            color: #6e8efb;
            transition: all 0.2s ease;
        }
        a:hover {
            color: #a777e3;
            text-decoration: underline;
        }
        .footer {
            background: linear-gradient(135deg, #2c3e50 0%, #1a1a2e 100%);
            color: white;
        }
        .footer a:hover {
            color: #a777e3;
            text-decoration: none;
        }
        .scroll-indicator {
            position: absolute;
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%);
            animation: bounce 2s infinite;
        }
        @keyframes bounce {
            0%, 20%, 50%, 80%, 100% {
                transform: translateY(0) translateX(-50%);
            }
            40% {
                transform: translateY(-20px) translateX(-50%);
            }
            60% {
                transform: translateY(-10px) translateX(-50%);
            }
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <section class="hero py-24 px-6 md:px-12 text-center relative">
        <div class="hero-content max-w-4xl mx-auto">
            <div class="flex justify-center mb-6">
                <div class="bg-white bg-opacity-20 p-3 rounded-full">
                    <i class="fas fa-cog fa-spin text-2xl text-white"></i>
                </div>
            </div>
            <h1 class="text-4xl md:text-5xl font-bold mb-6 font-serif">时间轮(Time Wheel)</h1>
            <p class="text-xl md:text-2xl mb-8 opacity-90 font-serif">高效管理定时任务的数据结构与技术实现</p>
            <p class="text-lg md:text-xl mb-10 opacity-80 max-w-3xl mx-auto">一种革命性的定时任务管理技术，为高并发系统提供高效的时间调度解决方案</p>
            <a href="#overview" class="inline-block bg-white text-blue-600 px-8 py-3 rounded-full font-semibold hover:bg-opacity-90 transition-all shadow-lg hover:shadow-xl">
                深入了解 <i class="fas fa-arrow-right ml-2"></i>
            </a>
        </div>
        <div class="scroll-indicator">
            <i class="fas fa-chevron-down text-white text-2xl opacity-70"></i>
        </div>
    </section>

    <!-- Overview Section -->
    <section id="overview" class="py-16 px-6 md:px-12 max-w-6xl mx-auto">
        <div class="mb-16">
            <h2 class="text-3xl font-bold mb-6 section-title">技术概述</h2>
            <div class="grid md:grid-cols-2 gap-8">
                <div>
                    <p class="text-lg mb-6">时间轮(Time Wheel)是一种高效管理定时任务的数据结构，特别适用于处理大量短期和长期定时任务的场景。它的核心思想是通过将时间划分为多个固定间隔的槽，每个槽代表一个时间段，槽内存储定时任务。当时间推进时，指针逐槽移动，当指针指向某个槽时，触发该槽中的所有任务。</p>
                    <p class="text-lg">时间轮的工作原理类似于时钟的秒针、分针和时针。每个时间段被分配到一个槽位(bucket)，每个槽位可以包含多个定时任务。当时间轮的指针移动到某个槽位时，执行该槽位中的所有任务。假如任务的时间超过一个轮的周期，任务会被重新放置到合适的槽位，等待下一轮循环时再执行。</p>
                </div>
                <div class="mermaid-container">
                    <div class="mermaid">
                        graph LR
                            A[时间轮] --> B[时间槽1]
                            A --> C[时间槽2]
                            A --> D[...]
                            A --> E[时间槽N]
                            
                            B --> F[任务1]
                            B --> G[任务2]
                            C --> H[任务3]
                            E --> I[任务M]
                            
                            style A fill:#6e8efb,stroke:#333,stroke-width:2px,color:#fff
                            style B fill:#a777e3,stroke:#333,stroke-width:1px,color:#fff
                            style C fill:#a777e3,stroke:#333,stroke-width:1px,color:#fff
                            style D fill:#a777e3,stroke:#333,stroke-width:1px,color:#fff
                            style E fill:#a777e3,stroke:#333,stroke-width:1px,color:#fff
                            style F fill:#f8f9fa,stroke:#666,stroke-width:1px
                            style G fill:#f8f9fa,stroke:#666,stroke-width:1px
                            style H fill:#f8f9fa,stroke:#666,stroke-width:1px
                            style I fill:#f8f9fa,stroke:#666,stroke-width:1px
                    </div>
                </div>
            </div>
        </div>

        <!-- Features Section -->
        <div class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">核心优势</h2>
            <div class="grid md:grid-cols-3 gap-8">
                <div class="card p-8">
                    <div class="flex items-center mb-4">
                        <i class="fas fa-bolt feature-icon"></i>
                        <h3 class="text-xl font-bold">高效性</h3>
                    </div>
                    <p>时间轮通过将时间离散化，将大量定时任务分配到不同的槽中，减少了系统对定时任务的遍历次数，提升了性能。</p>
                </div>
                <div class="card p-8">
                    <div class="flex items-center mb-4">
                        <i class="fas fa-expand feature-icon"></i>
                        <h3 class="text-xl font-bold">可扩展性</h3>
                    </div>
                    <p>时间轮可以很容易地适应不同规模的定时任务管理需求，适用于高并发的应用场景。</p>
                </div>
                <div class="card p-8">
                    <div class="flex items-center mb-4">
                        <i class="fas fa-network-wired feature-icon"></i>
                        <h3 class="text-xl font-bold">低延迟</h3>
                    </div>
                    <p>相比传统的定时器实现，时间轮在处理大量短期任务时能够显著降低调度延迟。</p>
                </div>
            </div>
        </div>
    </section>

    <!-- Java Implementation Section -->
    <section class="py-16 px-6 md:px-12 bg-gray-50">
        <div class="max-w-6xl mx-auto">
            <h2 class="text-3xl font-bold mb-8 section-title">Java中的应用实现</h2>
            
            <div class="grid md:grid-cols-2 gap-8 mb-12">
                <div>
                    <h3 class="text-2xl font-semibold mb-4 flex items-center">
                        <i class="fas fa-code mr-3 text-blue-500"></i>
                        Netty中的HashedWheelTimer
                    </h3>
                    <p class="mb-6">Netty是一个高性能的网络应用框架，在处理网络连接时，经常需要设置超时操作。Netty的<code class="bg-gray-200 px-1 rounded">HashedWheelTimer</code>类就是基于时间轮的实现，用于管理超时任务。通过将时间划分为多个槽，每个槽中可以存放多个定时任务，减少了全局扫描任务列表的开销。</p>
                    
                    <div class="code-block">
                        <div class="code-header">
                            <div class="code-dots">
                                <div class="dot dot-red"></div>
                                <div class="dot dot-yellow"></div>
                                <div class="dot dot-green"></div>
                            </div>
                            <span>HashedWheelTimer示例</span>
                        </div>
                        <pre class="p-4 overflow-x-auto"><code class="language-java">HashedWheelTimer timer = new HashedWheelTimer();

// 添加一个延迟任务
timer.newTimeout(timeout -> {
    System.out.println("任务执行！");
}, 5, TimeUnit.SECONDS);</code></pre>
                    </div>
                </div>
                
                <div>
                    <h3 class="text-2xl font-semibold mb-4 flex items-center">
                        <i class="fas fa-server mr-3 text-purple-500"></i>
                        其他应用场景
                    </h3>
                    <p class="mb-4">除了Netty，时间轮还可以用于以下场景：</p>
                    
                    <ul class="space-y-4">
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mr-3 mt-1"></i>
                            <div>
                                <span class="font-semibold">高并发环境下的延迟任务调度</span> - 例如在需要处理大量定时任务的分布式系统中，可以使用时间轮来减少CPU的调度开销。
                            </div>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mr-3 mt-1"></i>
                            <div>
                                <span class="font-semibold">网络包重传</span> - 在实现可靠的网络传输时，时间轮可以用于管理数据包的重传定时器。
                            </div>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mr-3 mt-1"></i>
                            <div>
                                <span class="font-semibold">缓存失效管理</span> - 在某些缓存系统中，使用时间轮可以高效管理缓存的过期时间，减少定时任务带来的系统开销。
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
            
            <div class="card p-8 bg-white">
                <h3 class="text-2xl font-semibold mb-6 flex items-center">
                    <i class="fas fa-lightbulb mr-3 text-yellow-500"></i>
                    技术比较：时间轮 vs 传统定时器
                </h3>
                
                <div class="overflow-x-auto">
                    <table class="min-w-full divide-y divide-gray-200">
                        <thead class="bg-gray-50">
                            <tr>
                                <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">特性</th>
                                <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">时间轮</th>
                                <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">传统定时器(堆实现)</th>
                            </tr>
                        </thead>
                        <tbody class="bg-white divide-y divide-gray-200">
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">时间复杂度(添加任务)</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">O(1)</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">O(log n)</td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">时间复杂度(执行任务)</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">O(1) per tick</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">O(1) per task</td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">内存使用</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">固定(预分配)</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">动态增长</td>
                            </tr>
                            <tr>
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">适用场景</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">大量短期定时任务</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">少量长期定时任务</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </section>

    <!-- Best Practices Section -->
    <section class="py-16 px-6 md:px-12 max-w-6xl mx-auto">
        <h2 class="text-3xl font-bold mb-8 section-title">最佳实践与优化建议</h2>
        
        <div class="grid md:grid-cols-2 gap-8 mb-12">
            <div class="card p-8">
                <h3 class="text-2xl font-semibold mb-4 flex items-center">
                    <i class="fas fa-cogs mr-3 text-blue-500"></i>
                    参数调优
                </h3>
                <ul class="space-y-3">
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 text-blue-500">
                            <i class="fas fa-clock"></i>
                        </div>
                        <p class="ml-3"><span class="font-semibold">时间粒度(tickDuration):</span> 根据业务需求选择合适的时间粒度，太短会增加CPU开销，太长会影响精度。</p>
                    </li>
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 text-blue-500">
                            <i class="fas fa-boxes"></i>
                        </div>
                        <p class="ml-3"><span class="font-semibold">槽位数(ticksPerWheel):</span> 需要根据最长延迟时间合理设置，避免任务被不必要地重新调度。</p>
                    </li>
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 text-blue-500">
                            <i class="fas fa-microchip"></i>
                        </div>
                        <p class="ml-3"><span class="font-semibold">线程数:</span> 在Netty中，通常使用单线程处理时间轮，避免多线程竞争。</p>
                    </li>
                </ul>
            </div>
            
            <div class="card p-8">
                <h3 class="text-2xl font-semibold mb-4 flex items-center">
                    <i class="fas fa-exclamation-triangle mr-3 text-red-500"></i>
                    注意事项
                </h3>
                <ul class="space-y-3">
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 text-red-500">
                            <i class="fas fa-ban"></i>
                        </div>
                        <p class="ml-3"><span class="font-semibold">避免长时间任务:</span> 时间轮不适合执行长时间运行的任务，会阻塞后续任务的执行。</p>
                    </li>
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 text-red-500">
                            <i class="fas fa-bolt"></i>
                        </div>
                        <p class="ml-3"><span class="font-semibold">任务公平性:</span> 时间轮不保证任务的执行顺序，同一槽位的任务执行顺序可能不确定。</p>
                    </li>
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 text-red-500">
                            <i class="fas fa-clock"></i>
                        </div>
                        <p class="ml-3"><span class="font-semibold">时间精度:</span> 时间轮的时间精度受限于时间粒度，不适合需要高精度定时的场景。</p>
                    </li>
                </ul>
            </div>
        </div>
        
        <div class="bg-blue-50 rounded-xl p-8 border border-blue-100">
            <h3 class="text-2xl font-semibold mb-4 flex items-center text-blue-700">
                <i class="fas fa-rocket mr-3"></i>
                高级扩展：分层时间轮
            </h3>
            <p class="mb-4 text-blue-800">对于需要支持很长延迟时间的场景，可以考虑使用分层时间轮(Hierarchical Timing Wheel)结构。这种结构类似于时钟的多级指针(秒针、分针、时针)，将时间轮分成多个层级，每个层级处理不同时间范围的定时任务。</p>
            
            <div class="mermaid-container bg-white mt-6">
                <div class="mermaid">
                    graph TB
                        subgraph 分层时间轮
                            A[第一层: 毫秒级] -->|溢出| B[第二层: 秒级]
                            B -->|溢出| C[第三层: 分级]
                            C -->|溢出| D[第四层: 时级]
                        end
                        
                        style A fill:#6e8efb,stroke:#333,color:#fff
                        style B fill:#a777e3,stroke:#333,color:#fff
                        style C fill:#4facfe,stroke:#333,color:#fff
                        style D fill:#00d2ff,stroke:#333,color:#fff
                </div>
            </div>
        </div>
    </section>

    <!-- Footer -->
    <footer class="footer py-12 px-6 md:px-12 text-center">
        <div class="max-w-6xl mx-auto">
            <div class="flex flex-col items-center justify-center">
                <div class="text-2xl font-bold mb-4">技术小馆</div>
                <div class="mb-6">
                    <a href="http://www.yuque.com/jtostring" class="text-white opacity-80 hover:opacity-100 transition-opacity">
                        <i class="fas fa-link mr-2"></i> http://www.yuque.com/jtostring
                    </a>
                </div>
                <div class="flex space-x-6">
                    <a href="#" class="text-white opacity-70 hover:opacity-100 transition-opacity">
                        <i class="fab fa-github text-xl"></i>
                    </a>
                    <a href="#" class="text-white opacity-70 hover:opacity-100 transition-opacity">
                        <i class="fab fa-twitter text-xl"></i>
                    </a>
                    <a href="#" class="text-white opacity-70 hover:opacity-100 transition-opacity">
                        <i class="fab fa-weixin text-xl"></i>
                    </a>
                </div>
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            fontFamily: '"Noto Sans SC", sans-serif',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>